package cn.ad.server.web.utils;

import cn.ad.server.common.utils.BeanUtils;
import cn.ad.server.domain.ad.DayTargert;
import cn.ad.server.domain.ad.Strategy;
import cn.ad.server.domain.enumration.MUniqueType;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

public class WebUtils {

	/**
	 * 24小时时间位
	 */
	private static int[] masks = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536,
			131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608 };

	public static void convetGetRequestParam(HttpServletRequest request, Object o) {
		Enumeration<String> enums = request.getParameterNames();
		Map<String, Object> map = new HashMap<String, Object>();
		while (enums.hasMoreElements()) {
			String name = enums.nextElement();
			String value = request.getParameter(name);
			map.put(name, value);
		}
		BeanUtils.copy(map, o);
	}

	/**
	 * 时间定向。匹配单位为小时。匹配周期为一周。 参数 date为null 则为当前时间。
	 * 
	 * @param strategy
	 * @param date
	 * @return
	 */
	public static boolean matchDayTarget(Strategy strategy, Date date) {
		if (strategy == null || strategy.getDayTargert() == null) {
			throw new IllegalArgumentException("org strategy illegal ");
		}
		DayTargert dayTargert = strategy.getDayTargert();
		if(strategy.getDayTargert()==null){
			return true;
		}
		Calendar calendar = Calendar.getInstance();
		if (date != null) {
			calendar.setTime(date);
		}
		int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
		int hour = calendar.get(Calendar.HOUR_OF_DAY);
		boolean validated = isTargetingTimeInternalRange(dayOfWeek, hour, dayTargert.toArray());
		return validated;
	}

	/**
	 * 配合方法 matchDayTarget(Strategy strategy, Date date)
	 * 
	 * @param dayOfWeek
	 * @param hour
	 * @param ranges
	 * @return
	 */
	private static boolean isTargetingTimeInternalRange(int dayOfWeek, int hour, Integer[] ranges) {
		return (ranges[dayOfWeek] & masks[hour]) != 0 ? true : false;
	}

	public static void main(String[] args) {
		Strategy s = new Strategy();
		DayTargert dt = new DayTargert();
		dt.setWednesday(Integer.MAX_VALUE);
		s.setDayTargert(dt);
		matchDayTarget(s, null);
	}
	
	/**
	 * 生成MUniqueId。
	 * 顺序依据：
	 *  MAC(1,"mac"),
	    MAC1(2,"mac1"),
	    IMEI(3,"imei"),
	    IDFA(4,"idfa"),
	    DUID(5,"duid"),
	    ANDROIDID(6,"androidid"),
	    UDID(7,"udid"),
	    AAID(8,"aaid"),
	    COOKIE(9,"cookieid");
	           先md5后sh1再ori
	 * @param adContext
	 * @return
	 */
	public static DeviceInfo generateMUniqueId(DeviceInfo adContext){
		DeviceInfo device = adContext; 
		boolean init = true;

		//MAC
		if (init) {
			if (StringUtils.hasText(device.getMac())) {
					adContext.setMuniqueType(MUniqueType.MAC);
					adContext.setMuniqueId(device.getMac());
					init = false;
			}
		}

		if (init) {
			if (StringUtils.hasText(device.getMacsh1())) {
					adContext.setMuniqueType(MUniqueType.MAC);
					adContext.setMuniqueId(device.getMacsh1());
					init = false;
			}
		}
		
		if (init) {
			if (StringUtils.hasText(device.getMacori())) {
				adContext.setMuniqueType(MUniqueType.MAC);
				adContext.setMuniqueId(device.getMacori());
				init = false;
			}
		}
		//mac1
		if (init) {
			if (StringUtils.hasText(device.getMac1())) {
				adContext.setMuniqueType(MUniqueType.MAC1);
				adContext.setMuniqueId(device.getMac1());
				init = false;
			}
		}
		
		if (init) {
			if (StringUtils.hasText(device.getMac1sh1())) {
				adContext.setMuniqueType(MUniqueType.MAC1);
				adContext.setMuniqueId(device.getMac1sh1());
				init = false;
			}
		}
		//IMEI
		if (init) {
			if (StringUtils.hasText(device.getImei())) {
				adContext.setMuniqueType(MUniqueType.IMEI);
				adContext.setMuniqueId(device.getImei());
				init = false;
			}
		}
		
		if (init) {
			if (StringUtils.hasText(device.getImeish1())) {
				adContext.setMuniqueType(MUniqueType.IMEI);
				adContext.setMuniqueId(device.getImeish1());
				init = false;
			}
		}
		
		if (init) {
			if (StringUtils.hasText(device.getImeiori())) {
				adContext.setMuniqueType(MUniqueType.IMEI);
				adContext.setMuniqueId(device.getImeiori());
				init = false;
			}
		}
		//IDFA
		if (init) {
			if (StringUtils.hasText(device.getIdfa())) {
				adContext.setMuniqueType(MUniqueType.IDFA);
				adContext.setMuniqueId(device.getIdfa());
				init = false;
			}
		}
		
		if (init) {
			if (StringUtils.hasText(device.getIdfash1())) {
				adContext.setMuniqueType(MUniqueType.IDFA);
				adContext.setMuniqueId(device.getIdfash1());
				init = false;
			}
		}
		
		if (init) {
			if (StringUtils.hasText(device.getIdfaori())) {
				adContext.setMuniqueType(MUniqueType.IDFA);
				adContext.setMuniqueId(device.getIdfaori());
				init = false;
			}
		}
		//DUID
		if (init) {
			if (StringUtils.hasText(device.getDuid())) {
				adContext.setMuniqueType(MUniqueType.DUID);
				adContext.setMuniqueId(device.getDuid());
				init = false;
			}
		}
		
		if (init) {
			if (StringUtils.hasText(device.getDuidsh1())) {
				adContext.setMuniqueType(MUniqueType.DUID);
				adContext.setMuniqueId(device.getDuidsh1());
				init = false;
			}
		}
		
	
		//anid
		if (init) {
			if (StringUtils.hasText(device.getAnid())) {
				adContext.setMuniqueType(MUniqueType.ANDROIDID);
				adContext.setMuniqueId(device.getAnid());
				init = false;
			}
		}
		
		if (init) {
			if (StringUtils.hasText(device.getAnidsh1())) {
				adContext.setMuniqueType(MUniqueType.ANDROIDID);
				adContext.setMuniqueId(device.getAnidsh1());
				init = false;
			}
		}
		
		if (init) {
			if (StringUtils.hasText(device.getAnidori())) {
				adContext.setMuniqueType(MUniqueType.ANDROIDID);
				adContext.setMuniqueId(device.getAnidori());
				init = false;
			}
		}
		//UDID
		if (init) {
			if (StringUtils.hasText(device.getUdid())) {
				adContext.setMuniqueType(MUniqueType.UDID);
				adContext.setMuniqueId(device.getUdid());
				init = false;
			}
		}
		
		if (init) {
			if (StringUtils.hasText(device.getUdidsh1())) {
				adContext.setMuniqueType(MUniqueType.UDID);
				adContext.setMuniqueId(device.getUdidsh1());
				init = false;
			}
		}
		
		//AAID
		if (init) {
			if (StringUtils.hasText(device.getAaid())) {
				adContext.setMuniqueType(MUniqueType.AAID);
				adContext.setMuniqueId(device.getAaid());
				init = false;
			}
		}
		
		if (init) {
			if (StringUtils.hasText(device.getAaidsh1())) {
				adContext.setMuniqueType(MUniqueType.AAID);
				adContext.setMuniqueId(device.getAaidsh1());
				init = false;
			}
		}
		
		//COOKIE
		if (init) {
			if (StringUtils.hasText(device.getCookieid())) {
				adContext.setMuniqueType(MUniqueType.COOKIE);
				adContext.setMuniqueId(device.getCookieid());
				init = false;
			}
		}

		return adContext;
	}
	
	
	public static class DeviceInfo {
		/**
		 * 用户终端的 IMEI，15 位数字，md5 加密
		 */
		private String imei;
		
		/**
		 * 用户终端的 IMEI，15 位数字，sh1 加密
		 */
		private String imeish1;

		/**
		 * 原始imei，建议和imei一起传给sever端
		 */
		private String imeiori;
		
		/**
		 * IOS IDFA 适用于 IOS6 及以上，md5 加密
		 */
		private String idfa;
		/**
		 * IOS IDFA 适用于 IOS6 及以上，sh1加密
		 */
		private String idfash1;

		/**
		 * 原始idfa，建议和idfa一起传给sever端
		 */
		private String idfaori;
		
		/**
		 * Android ID，仅适用于 Android 设备，md5 加密
		 */
		private String anid;
		/**
		 * Android ID，仅适用于 Android 设备，sh1 加密
		 */
		private String anidsh1;

		/**
		 * 原始Android ID，建议和anid一起传给sever端
		 */
		private String anidori;
		
		/**
		 * Android Advertising ID，md5 加密
		 */
		private String aaid;
		/**
		 * Android Advertising ID，sh1 加密
		 */
		private String aaidsh1;
		
		/**
		 * 用户终端的 eth0 接口的 MAC 地址（大写去除冒号分隔符）， md5 加密
		 */
		private String mac;
		/**
		 * 用户终端的 eth0 接口的 MAC 地址（大写去除冒号分隔符）， sh1 加密
		 */
		private String macsh1;

		/**
		 * 原始mac，建议和mac一起传给sever端
		 */
		private String macori;
		
		/**
		 * IOS UDID，md5 加密
		 */
		private String udid;
		/**
		 * IOS UDID，sh1 加密
		 */
		private String udidsh1;

		/**
		 * Windows Phone 用户终端的 DUID，md5 加密
		 */
		private String duid;
		/**
		 * Windows Phone 用户终端的 DUID，sh1 加密
		 */
		private String duidsh1;

		/**
		 * 用户终端的 eth0 接口的 MAC 地址（大写且保留冒号分隔符），md5 加密
		 */
		private String mac1;
		/**
		 * 用户终端的 eth0 接口的 MAC 地址（大写且保留冒号分隔符），sh1 加密
		 */
		private String mac1sh1;
		
		/**
		 * 用户cookieid
		 */
		private String cookieid;
		/**
		 * 跟踪使用的唯一串号类型
		 */
		private MUniqueType muniqueType;
		
		/**
		 * 跟踪使用的唯一串号
		 */
		private String muniqueId;

		public String getImei() {
			return imei;
		}

		public void setImei(String imei) {
			this.imei = imei;
		}

		public String getImeiori() {
			return imeiori;
		}

		public void setImeiori(String imeiori) {
			this.imeiori = imeiori;
		}

		public String getIdfa() {
			return idfa;
		}

		public void setIdfa(String idfa) {
			this.idfa = idfa;
		}

		public String getIdfaori() {
			return idfaori;
		}

		public void setIdfaori(String idfaori) {
			this.idfaori = idfaori;
		}

		public String getAnid() {
			return anid;
		}

		public void setAnid(String anid) {
			this.anid = anid;
		}

		public String getAnidori() {
			return anidori;
		}

		public void setAnidori(String anidori) {
			this.anidori = anidori;
		}

		public String getAaid() {
			return aaid;
		}

		public void setAaid(String aaid) {
			this.aaid = aaid;
		}

		public String getMac() {
			return mac;
		}

		public void setMac(String mac) {
			this.mac = mac;
		}

		public String getMacori() {
			return macori;
		}

		public void setMacori(String macori) {
			this.macori = macori;
		}

		public String getUdid() {
			return udid;
		}

		public void setUdid(String udid) {
			this.udid = udid;
		}

		public String getDuid() {
			return duid;
		}

		public void setDuid(String duid) {
			this.duid = duid;
		}

		public String getMac1() {
			return mac1;
		}

		public void setMac1(String mac1) {
			this.mac1 = mac1;
		}

		public String getCookieid() {
			return cookieid;
		}

		public void setCookieid(String cookieid) {
			this.cookieid = cookieid;
		}

		public MUniqueType getMuniqueType() {
			return muniqueType;
		}

		public void setMuniqueType(MUniqueType muniqueType) {
			this.muniqueType = muniqueType;
		}

		public String getMuniqueId() {
			return muniqueId;
		}

		public void setMuniqueId(String muniqueId) {
			this.muniqueId = muniqueId;
		}

		public String getImeish1() {
			return imeish1;
		}

		public void setImeish1(String imeish1) {
			this.imeish1 = imeish1;
		}

		public String getIdfash1() {
			return idfash1;
		}

		public void setIdfash1(String idfash1) {
			this.idfash1 = idfash1;
		}

		public String getAnidsh1() {
			return anidsh1;
		}

		public void setAnidsh1(String anidsh1) {
			this.anidsh1 = anidsh1;
		}

		public String getAaidsh1() {
			return aaidsh1;
		}

		public void setAaidsh1(String aaidsh1) {
			this.aaidsh1 = aaidsh1;
		}

		public String getMacsh1() {
			return macsh1;
		}

		public void setMacsh1(String macsh1) {
			this.macsh1 = macsh1;
		}

		public String getUdidsh1() {
			return udidsh1;
		}

		public void setUdidsh1(String udidsh1) {
			this.udidsh1 = udidsh1;
		}

		public String getDuidsh1() {
			return duidsh1;
		}

		public void setDuidsh1(String duidsh1) {
			this.duidsh1 = duidsh1;
		}

		public String getMac1sh1() {
			return mac1sh1;
		}

		public void setMac1sh1(String mac1sh1) {
			this.mac1sh1 = mac1sh1;
		}
		
	}

	public static Object invokeGetValue(Object object, String propertyName, Object... parameters) {

		Object o = null;
		try {
			PropertyDescriptor propertyDescriptor = new PropertyDescriptor(propertyName, object.getClass());
			Method readMethod = propertyDescriptor.getReadMethod();
			o = readMethod.invoke(object, parameters);
		} catch (IntrospectionException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}

		return o;
	}

}
